#include	"telnetd.h"
#include	"cmd_handler.h"
#include <tchar.h>
#include <strsafe.h>

#define DEFAULT_FAMILY  AF_UNSPEC
#define DEFAULT_SOCKTYPE SOCK_STREAM
#define DEFAULT_PORT  23
#define BUFFER_SIZE   1024
#define	DEFAULT_USER	 "root"
#define	DEFAULT_PASSWORD "wave"

int authencate(SOCKET sock)
{
	char buf[256], *line_end;
	int pos = 0;
	send(sock, "username: ", strlen("username: "), 0);
	memset(buf, 0, sizeof(buf));
	do
	{
		pos += recv(sock, &(buf[pos]), sizeof(buf)-pos, 0);
		line_end = strchr(buf, '\n');
	} while(line_end == NULL);
	if(strncmp(DEFAULT_USER, buf, line_end - buf != 0))
		return 0;

	send(sock, "password: ", strlen("password: "), 0);
	pos = 0;
	memset(buf, 0, sizeof(buf));
	do
	{
		pos += recv(sock, &(buf[pos]), sizeof(buf)-pos, 0);
		line_end = strchr(buf, '\n');
	} while(line_end == NULL);
	if(strncmp(DEFAULT_PASSWORD, buf, line_end - buf != 0))
		return 0;
	return 1;
}

void start()
{
	SOCKET sock, socksvr = INVALID_SOCKET;
	char line[BUFFER_SIZE], cmd[BUFFER_SIZE], out[10*BUFFER_SIZE];
	int pos, i;
    
    int cbXfer;
	struct sockaddr_in addr;

    sock = INVALID_SOCKET;
	socksvr = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("0.0.0.0");
	addr.sin_port = htons(DEFAULT_PORT);

	bind(socksvr, (SOCKADDR*)(&addr), sizeof(SOCKADDR));
	listen(socksvr, 5);
	while(1)
	{
		sock = accept(socksvr, NULL, NULL);
		if(sock == INVALID_SOCKET) 
		{
			printf("ERROR: accept() failed with error = %d\r\n", WSAGetLastError());
			goto Cleanup;
		}

		printf("Accepted TCP connection from socket 0x%08x\r\n", sock);
		
		if(!authencate(sock))
		{
			shutdown(sock, SD_BOTH);
			closesocket(sock);
			continue;
		}

		send(sock, "/$ ", strlen("/$ "), 0);
		pos = 0;
		do{
			cbXfer = recv(sock, &(line[pos]), BUFFER_SIZE-pos, 0);
			if(cbXfer == 0)
			{
				shutdown(sock, SD_BOTH);
				closesocket(sock);
				break;
			}
			send(sock, "", 1, 0); // cause echo
			pos += cbXfer;
			
			if(line[pos-1] == '\4')
			{
				shutdown(sock, SD_BOTH);
				closesocket(sock);
				break;
			}
			if(line[pos-1] == '\n')
			{
				if(pos > 2)
				{
				strncpy_s(cmd, sizeof(cmd), line, pos-2); // don't copy the last line break
				out[0] = 0;
				exec_cmd(cmd, sock);
				send(sock, out, strlen(out), 0);
				}
				pos = 0;
				send(sock, "/$ ", strlen("/$ "), 0);
			}
		} while(cbXfer > 0);
	}

Cleanup:
    closesocket(socksvr);

    if(sock != INVALID_SOCKET)
    {
        shutdown(sock, SD_BOTH);
        closesocket(sock);
    }

    return;
} 